jacquardSnapshot

← snapshot

3082 bytes
import { WeaveArchive, type Artifact } from "@/components/weave-archive";
import { api } from "@/lib/api";
import type { DecisionDto, SnapshotDto } from "@/lib/types";

export const dynamic = "force-dynamic";

/**
 * Everything this repo has woven, in one ledger.
 *
 * The other pages each show one kind of thing. This shows the whole bolt —
 * snapshots, the source inside them, decisions, the attestations that settled
 * them, and the refs pointing at any of it — in the order it was made, with
 * provenance as the axis you sort and filter by.
 *
 * Assembled across every ref rather than the default one, because history
 * that only exists on a branch is still history.
 */
export default async function WeavePage({
  params,
}: {
  params: Promise<{ repo: string }>;
}) {
  const { repo } = await params;
  const detail = await api.repo(repo);

  // Walk every ref; a snapshot reachable from two refs is still one artifact.
  const logs = await Promise.all(
    detail.refs.map((r) =>
      api
        .log(repo, r.name, 200)
        .then((l) => ({ ref: r.name, entries: l.entries }))
        .catch(() => ({ ref: r.name, entries: [] as SnapshotDto[] })),
    ),
  );

  const snapshots = new Map<string, SnapshotDto>();
  const refsBySnapshot = new Map<string, string[]>();
  for (const { ref, entries } of logs) {
    for (const s of entries) snapshots.set(s.id, s);
  }
  for (const r of detail.refs) {
    const at = refsBySnapshot.get(r.head) ?? [];
    at.push(r.name);
    refsBySnapshot.set(r.head, at);
  }

  const decisions: DecisionDto[] = await api
    .decisions(repo)
    .then((d) => d.decisions)
    .catch(() => []);

  const artifacts: Artifact[] = [];

  for (const s of snapshots.values()) {
    artifacts.push({
      kind: "snapshot",
      id: s.id,
      short: s.short,
      at: s.at,
      title: s.message,
      provenance: s.provenance,
      actor: s.author,
      refs: refsBySnapshot.get(s.id) ?? [],
      parents: s.parents,
      tree: s.tree,
    });
  }

  for (const d of decisions) {
    artifacts.push({
      kind: "decision",
      id: d.id,
      short: d.short,
      at: d.at,
      title: d.title,
      // A decision is a machine's or a person's *proposal*; it carries the
      // proposer's hand, never an attestation's.
      provenance: d.proposed_by.kind === "human" ? "human" : "agent",
      actor: d.proposed_by,
      rationale: d.rationale,
      families: d.families,
      scope: d.scope,
      state: d.state,
    });
    if (d.attestation) {
      artifacts.push({
        kind: "attestation",
        id: d.attestation.id,
        short: d.attestation.id.slice(0, 12),
        at: d.attestation.at,
        title: d.title,
        provenance: "human",
        actor: d.attestation.attestor,
        statement: d.attestation.statement,
        decision: d.id,
      });
    }
  }

  artifacts.sort((a, b) => b.at - a.at || a.id.localeCompare(b.id));

  return (
    <WeaveArchive
      repo={repo}
      artifacts={artifacts}
      objectCount={detail.object_count}
      refs={detail.refs}
    />
  );
}